#include "qdataoperator.h"

#include "qlinearintconfigdialog.h"
#include "qcustomoperatioeditordialog.h"
#include "qcustomscriptobject.h"
#include "qlinearfloatconfigdialog.h"

#include "../../libs/device/qdevicemanager.h"
#include "../../libs/device/data_sync/qserverdatasync.h"

#include <QScriptEngine>
#include <QScriptValue>

QAbstractDataOperator::QAbstractDataOperator(const QString &device_uuid,
                                             tagDataInfo* data,
                                             QDeviceManager *device,
                                             int time):
    QObject(NULL),
    m_device_uuid(device_uuid),
    m_device_manager(device),
    m_data(data),
    m_timer(new QTimer),
    m_value(data->m_value),
    m_period(time)
{
    if(m_period<=30)
    {
        m_period=1000;
    }
    m_last_time=QDateTime::currentDateTime();
    connect(m_timer,SIGNAL(timeout()),this,SLOT(run()));
}


QAbstractDataOperator::~QAbstractDataOperator()
{
    delete m_timer;
}

bool QAbstractDataOperator::edit(QWidget *)
{
    m_timer->start(30);
    return true;
}

void QAbstractDataOperator::run()
{
    QDateTime dt=QDateTime::currentDateTime();
    if(m_last_time.msecsTo(dt)>=m_period)
    {
        if(make_value())
        {
            m_device_manager->set_value(m_device_uuid,m_data->m_uuid,m_value);
        }
        m_last_time=dt;
    }
}

bool QAbstractDataOperator::make_value()
{
    return false;
}


QStaticDataOPerator::QStaticDataOPerator(const QString &device_uuid,
                                         tagDataInfo *data,
                                         QDeviceManager *device):
    QAbstractDataOperator(device_uuid,data,device)
{

}


QLinearIntOperator::QLinearIntOperator(const QString &device_uuid,
                                       tagDataInfo *data,
                                       QDeviceManager *device):
    QAbstractDataOperator(device_uuid,data,device),
    m_step(1)
{

}

bool QLinearIntOperator::make_value()
{
    if(m_step==0)
    {
        return false;
    }
    int v=m_data->m_value.toInt();

    v+=m_step;
    m_value=v;

    return true;
}

bool QLinearIntOperator::edit(QWidget *parent)
{
    QLinearIntConfigDialog dlg(parent);
    dlg.exec();

    if(dlg.get_period()>0)
    {
        m_period=dlg.get_period();
        m_step=dlg.get_step();
        return QAbstractDataOperator::edit(parent);
    }
    else
    {
        return false;
    }
}


QLinearFloatOperator::QLinearFloatOperator(const QString &device_uuid,
                                       tagDataInfo *data,
                                       QDeviceManager *device):
    QAbstractDataOperator(device_uuid,data,device),
    m_step(1)
{

}

bool QLinearFloatOperator::make_value()
{
    if(m_step==0)
    {
        return false;
    }
    float v=m_data->m_value.toFloat();

    v+=m_step;
    m_value=v;

    return true;
}

bool QLinearFloatOperator::edit(QWidget *parent)
{
    QLinearFloatConfigDialog dlg(parent);
    dlg.exec();

    if(dlg.get_period()>0)
    {
        m_period=dlg.get_period();
        m_step=dlg.get_step();
        return QAbstractDataOperator::edit(parent);
    }
    else
    {
        return false;
    }
}

QCustomOperator::QCustomOperator(const QString &device_uuid,
                                 tagDataInfo *data,
                                 QDeviceManager *device):
    QAbstractDataOperator(device_uuid,data,device),
    m_count(0)
{
}

bool QCustomOperator::make_value()
{
    if(m_code=="")
    {
        return false;
    }

    QScriptEngine engine;

    QCustomScriptObject o;

    QScriptValue global=engine.newQObject(&o);

    global.setProperty("count",m_count);
    if(m_data->m_type=="Number")
    {
        global.setProperty("last_value",m_data->m_value.toInt());
        global.setProperty("value",m_value.toInt());
    }
    else if(m_data->m_type=="Bool")
    {
        global.setProperty("last_value",m_data->m_value.toBool());
        global.setProperty("value",m_value.toBool());
    }
    else if(m_data->m_type=="Float")
    {
        global.setProperty("last_value",m_data->m_value.toFloat());
        global.setProperty("value",m_value.toFloat());
    }
    else
    {
        global.setProperty("last_value",m_data->m_value.toString());
        global.setProperty("value",m_value.toString());
    }

    engine.setGlobalObject(global);

    engine.evaluate(m_code);

    if(engine.hasUncaughtException())
    {
        m_code="";
        qDebug(engine.uncaughtException().toString().toLocal8Bit());
        return false;
    }
    else
    {
        m_count++;
        m_value=engine.globalObject().property("value").toVariant();
        if(m_data->m_type=="Number")
        {
            m_value=m_value.toInt();
        }
        else if(m_data->m_type=="Bool")
        {
            m_value=m_value.toBool();
        }
        else if(m_data->m_type=="Float")
        {
            m_value=m_value.toFloat();
        }
        else
        {
            m_value=m_value.toString();
        }
        return true;
    }
}

bool QCustomOperator::edit(QWidget *parent)
{

    QCustomOperatioEditorDialog dlg(parent);

    dlg.exec();

    if(dlg.get_code()!="")
    {
        m_code=dlg.get_code();
        m_period=dlg.get_period();
        return QAbstractDataOperator::edit(parent);
    }
    return false;
}
